package com.hulk.ratel.manage.commonutil;




import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hulk.ratel.common.constant.enums.BussErrCode;
import com.hulk.ratel.common.exception.ManageRteException;
import com.hulk.ratel.common.security.ConsumeSecurityWarper;
import com.hulk.ratel.common.util.SaltGenerator;
import com.hulk.ratel.manage.commoncache.PartnerKeyCache;
import com.hulk.ratel.manage.commoncache.SecurityPartnerCache;
import com.hulk.ratel.persistence.entity.PartnerKey;
import com.hulk.ratel.service.dto.AsyncParamRespDTO;
import com.hulk.ratel.service.dto.SyncRespDTO;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import lombok.NonNull;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Optional;

/**
 * Created by hulk on 2017/5/2.
 * 报文处理工具类
 */
@Slf4j
@Component
@AllArgsConstructor
public class ContentUtil {


    private SecurityPartnerCache cspc;

    private PartnerKeyCache pkc;

    private ObjectMapper om;


    /**
     * 验签
     *
     * @param workId
     * @param partnerNo
     * @param plainText
     * @param signature
     */
    public boolean checkSign(@NonNull String plainText, @NonNull String signature, String partnerNo, String workId) {
        boolean checkResult = false;
        //合作方密钥查询
        PartnerKey platformKey = pkc.findPartnerKey(partnerNo);
        if (null == platformKey) {
            log.error("workId:{} 密钥信息不存在！partnerNo：{}", workId, partnerNo);
            return false;
        }
        String platformPrivateKeyStr = platformKey.getPlatformPrivatekey();
        //String platformKeyKeySuffix = platformKeyKeyStr.substring(platformKeyKeyStr.lastIndexOf(".") + 1);
        String platformPrivateKeySuffix = platformKey.getPlatformPrivatekeySuffix();
        String KeypathType=  platformKey.getKeypathType();
        PrivateKey privateKey = Optional.of(cspc.findPrivateKey(partnerNo,platformPrivateKeyStr, platformPrivateKeySuffix, KeypathType)).get();
        String signStr = ConsumeSecurityWarper.getSignB64PlainTextByPartnerPrivateKey(plainText, privateKey);

        try {
            signStr = URLEncoder.encode(signStr, StandardCharsets.UTF_8.name());
            signature = URLEncoder.encode(signature, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%2B");
        } catch (UnsupportedEncodingException e) {
            log.error("workId:{} 验签异样！partnerNo：{}{}", workId, partnerNo, e);
            return false;
        }
        if (signature.equals(signStr)) {
            checkResult = true;
        }
        log.info("workId:{} 验签结果：{}", workId, checkResult);
        return checkResult;
    }

    /**
     * @param workId
     * @param partnerNo
     * @param plainText
     */
    public String sign(@NonNull String plainText, @NonNull String partnerNo, String workId) {
        String signStr;
        //合作方密钥查询
        PartnerKey platformKey = pkc.findPartnerKey( partnerNo);
        if (null == platformKey) {
            log.error("workId:{} 密钥信息不存在！partnerNo：{}", workId, partnerNo);
            throw new ManageRteException(workId, BussErrCode.E_100010.getErrCode(), BussErrCode.E_100010.getErrDesc());
        }
        String platformPrivateKeyStr = platformKey.getPlatformPrivatekey();
        //String platformPrivateKeySuffix = platformKeyKeyStr.substring(platformKeyKeyStr.lastIndexOf(".") + 1);
        String platformPrivateKeySuffix = platformKey.getPlatformPrivatekeySuffix();
        String keypathType=  platformKey.getKeypathType();
        PrivateKey privateKey =  Optional.of(cspc.findPrivateKey(partnerNo,platformPrivateKeyStr, platformPrivateKeySuffix, keypathType)).get();
        signStr = ConsumeSecurityWarper.getSignB64PlainTextByPartnerPrivateKey(plainText, privateKey);
        return signStr;
    }
    @SneakyThrows
    public String postHandle(@NonNull Object resp, @NonNull String partnerAESKey, @NonNull String partnerNo, String workId) {
        //合作方密钥查询
        PartnerKey platformKey = Optional.of(pkc.findPartnerKey(partnerNo)).get();

        String platformPrivateKeyStr = platformKey.getPlatformPrivatekey();
        String platformPrivateKeySuffix = platformKey.getPlatformPrivatekeySuffix();
        String keypathType =  platformKey.getKeypathType();
        PrivateKey privateKey = Optional.of(cspc.findPrivateKey(partnerNo,platformPrivateKeyStr, platformPrivateKeySuffix, keypathType)).get();

        String bodyJson = om.writeValueAsString(resp);

        String rCipherB64PlainText = ConsumeSecurityWarper.getCipherB64PlainTextByPartnerAESKey(bodyJson, partnerAESKey);
        String rSignlainText = ConsumeSecurityWarper.getSignB64PlainTextByPartnerPrivateKey(bodyJson, privateKey);

        SyncRespDTO syncRespDTO = new SyncRespDTO();
        syncRespDTO.setCipherPartnerAES(rCipherB64PlainText);
        syncRespDTO.setSignPlatformPrivateKey(rSignlainText);

        String    syncRespPlanText = om.writeValueAsString(syncRespDTO);

        log.info("同步返回报文内容: workId:{}, partnerNo:{}, 明文: bodyJson:{}, 密文：syncRespPlanText:{}, partnerAESKey:{}", workId, partnerNo, bodyJson, syncRespPlanText, partnerAESKey);
        return syncRespPlanText;
    }
    @SneakyThrows
    public AsyncParamRespDTO postHandleAsync(@NonNull Object resp, @NonNull String traceId, @NonNull String partnerNo, String workId) {
        //合作方密钥查询
        PartnerKey partnerKey = Optional.of(pkc.findPartnerKey(partnerNo)).get();
        String platformKeyKeyStr = partnerKey.getPlatformPrivatekey();

        String platformKPrivateKeySuffix = partnerKey.getPlatformPrivatekeySuffix();
        String partnerPublicKeyStr = partnerKey.getPartnerPublickey();

        String partnerPublicKeySuffix = partnerKey.getPartnerPublickeySuffix();
        PrivateKey privateKey = Optional.of(cspc.findPrivateKey(partnerNo,platformKeyKeyStr, platformKPrivateKeySuffix, partnerKey.getKeypathType())).get();
        PublicKey publicKey = Optional.of(cspc.findPublicKey(partnerNo,partnerPublicKeyStr, partnerPublicKeySuffix, partnerKey.getKeypathType())).get();
        String  bodyJson = om.writeValueAsString(resp);
        String partnerAESKey = SaltGenerator.generate();
        String partnerEncryptAesKey = ConsumeSecurityWarper.getCipherB64AESKeyByPlatformPublicKey(partnerAESKey, publicKey);
        String rCipherB64PlainText = ConsumeSecurityWarper.getCipherB64PlainTextByPartnerAESKey(bodyJson, partnerAESKey);
        String rSignB64PlainText = ConsumeSecurityWarper.getSignB64PlainTextByPartnerPrivateKey(bodyJson, privateKey);

        AsyncParamRespDTO asyncRespDTO = new AsyncParamRespDTO();
        asyncRespDTO.setTraceId(traceId);
        asyncRespDTO.setEncryptData(rCipherB64PlainText);
        asyncRespDTO.setEncryptKey(partnerEncryptAesKey);
        asyncRespDTO.setSignature(rSignB64PlainText);
        asyncRespDTO.setExt("");
        log.info("同步返回报文内容: workId:{},traceId:{}, partnerNo:{}, 明文: bodyJson:{}, 密文：asyncRespPlanText:{}, partnerAESKey:{}", workId, traceId, partnerNo, bodyJson, rCipherB64PlainText, partnerAESKey);
        return asyncRespDTO;
    }
}
